﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Soundteller.Audio.Model;
using Soundteller.Audio.Repositories;
using Soundteller.Audio.Repositories.Interfaces;
using Soundteller.Common.Tests;
using Soundteller.Audio.Model.Interfaces;
using Moq;
using System.Collections.Generic;

namespace Soundteller.Audio.Tests.Unit.Repositories.SoundBufferRepositorySpecifications
{
    public abstract class WhenPush : TestBase
    {
        protected ISoundBufferRepository SoundBufferRepository { get; private set; }
        protected Mock<IMemoryContext> Context { get; private set; }
        protected abstract Sound SoundToAdd { get; }

        protected override void Arrange()
        {
            Context = new Mock<IMemoryContext>();
            SoundBufferRepository = new SoundBufferRepository(Context.Object);
        }

        protected override void Act()
        {
            SoundBufferRepository.Push(SoundToAdd);
        }
    }

    [TestClass]
    public class WhenPushGivenEmptySound : WhenPush
    {
        protected override Sound SoundToAdd
        {
            get { return null; }
        }

        protected override void Act()
        {
            ExpectException(() => base.Act());
        }

        [TestMethod]
        public void ThenAnArgumentNullExceptionShouldBeThrown()
        {
            Exception.VerifyArgumentNullException("sound");
        }
    }

    [TestClass]
    public class WhenPushGivenEmptyBuffer : WhenPush
    {
        private Sound _soundToAdd;
        private Sound _addedSound;
        private Stack<Sound> _buffer;

        protected override Sound SoundToAdd
        {
            get
            {
                if (_soundToAdd == null) _soundToAdd = new Sound();

                return _soundToAdd;
            }
        }

        protected override void Arrange()
        {
            base.Arrange();

            _buffer = new Stack<Sound>();
            Context.Setup(c => c.SoundBuffer).Returns(_buffer);
        }

        protected override void Act()
        {
            base.Act();
            _addedSound = SoundBufferRepository.Pop();
        }

        [TestMethod]
        public void ThenPopShouldReturnAddedSound()
        {
            Assert.AreEqual(_soundToAdd, _addedSound);
        }
    }
}
